#include <stdint.h>
#include "rs485.h"
#include <string.h>
#include "usart.h"

// 模块私有变量
static UART_HandleTypeDef *sensor_huart = NULL;
static SensorError_t last_error = SENSOR_OK;

extern osMessageQueueId_t sensorQueueHandle;

//--------------SoilSensor_ReadData函数--------
uint8_t tx_buffer[8];
uint8_t rx_buffer[13]; // 响应帧长度: 1(地址)+1(功能码)+1(字节数)+8(数据)+2(CRC)=13

SensorQueue_t sensor_data;


// Modbus相关定义
#define SENSOR_ADDRESS 0x01
#define MODBUS_READ_HOLDING_REGISTERS 0x03

// 寄存器地址
#define REG_TEMPERATURE 0x0000
#define REG_HUMIDITY    0x0001
#define REG_EC    0x0002
#define REG_CONDUCTIVITY 0x0003

// 响应超时时间(ms)
#define RESPONSE_TIMEOUT 100

// CRC16计算函数 (Modbus标准)
uint16_t SoilSensor_CRC16(uint8_t *data, uint16_t length)
{
    uint16_t crc = 0xFFFF;

    for (uint16_t i = 0; i < length; i++)
    {
        crc ^= data[i];

        for (uint8_t j = 0; j < 8; j++)
        {
            if (crc & 0x0001)
            {
                crc = (crc >> 1) ^ 0xA001;
            }
            else
            {
                crc = crc >> 1;
            }
        }
    }

    return crc;
}

// 库初始化
void SoilSensor_Init(UART_HandleTypeDef *huart, osMessageQueueId_t dataQueue)
{
    sensor_huart = huart;
    sensorQueueHandle = dataQueue;
    last_error = SENSOR_OK;
}

// 获取最后错误信息
SensorError_t SoilSensor_GetLastError(void)
{
    return last_error;
}

// 构建Modbus读取请求
static uint16_t BuildReadRequest(uint8_t *buffer, uint16_t startReg, uint16_t numRegs)
{
    buffer[0] = SENSOR_ADDRESS;                 // 设备地址
    buffer[1] = MODBUS_READ_HOLDING_REGISTERS;  // 功能码
    buffer[2] = (startReg >> 8) & 0xFF;         // 起始寄存器高字节
    buffer[3] = startReg & 0xFF;                // 起始寄存器低字节
    buffer[4] = (numRegs >> 8) & 0xFF;          // 寄存器数量高字节
    buffer[5] = numRegs & 0xFF;                 // 寄存器数量低字节

    // 计算CRC
    uint16_t crc = SoilSensor_CRC16(buffer, 6);
    buffer[6] = crc & 0xFF;                     // CRC低字节
    buffer[7] = (crc >> 8) & 0xFF;              // CRC高字节

    return 8; // 返回请求帧长度
}

// 解析Modbus响应
// 解析Modbus响应
static SensorError_t ParseModbusResponse(uint8_t *response, uint16_t length, SensorQueue_t *data)
{
    if (length < 13) return SENSOR_INVALID_RESPONSE;

    // CRC校验（低字节在前）
    uint16_t received_crc = response[length-2] | (response[length-1] << 8);
    uint16_t calculated_crc = SoilSensor_CRC16(response, length-2);
    if (received_crc != calculated_crc) return SENSOR_CRC_ERROR;

    if (response[1] != MODBUS_READ_HOLDING_REGISTERS) return SENSOR_INVALID_RESPONSE;
    if (response[2] != 8) return SENSOR_INVALID_RESPONSE; // 应该返回8字节数据

    // 按手册顺序解析
    int16_t humid_raw = (response[3] << 8) | response[4];
    int16_t temp_raw  = (response[5] << 8) | response[6];
    int16_t sal_raw   = (response[7] << 8) | response[8];
    // int16_t cond_raw  = (response[9] << 8) | response[10];


    // 处理数据的转换
    if (temp_raw > 80) { // 传感器温度正负判断
        data->temperature = -((0x10000 - temp_raw) / 10.0f);  // 如果大于80，表示负温度
    } else {
        data->temperature = temp_raw / 10.0f;
    }
    data->humidity    = humid_raw / 10.0f;  // %
    data->EC    = sal_raw;    // μS/cm

    if (data->temperature < -40.0f || data->temperature > 80.0f ||
        data->humidity < 0.0f || data->humidity > 100.0f ||
        data->EC < 0.0f || data->EC > 20000.0f)
    {
        return SENSOR_INVALID_DATA;
    }

    return SENSOR_OK;
}


// 数据采集函数
SensorError_t SoilSensor_ReadData(void)
{
    if (sensor_huart == NULL || sensorQueueHandle == NULL)
    {
        last_error = SENSOR_INVALID_RESPONSE;
        return last_error;
    }

    // 构建读取请求
    uint16_t tx_length = BuildReadRequest(tx_buffer, REG_TEMPERATURE, 4);

    // 发送请求
    if (HAL_UART_Transmit(sensor_huart, tx_buffer, tx_length, RESPONSE_TIMEOUT) != HAL_OK)
    {
        last_error = SENSOR_TIMEOUT;
        return last_error;
    }

    // 开始接收数据
    uint32_t timeout = HAL_GetTick() + RESPONSE_TIMEOUT;
    HAL_UART_Receive_IT(sensor_huart, rx_buffer, 13);  // 启动中断接收

    // 检查是否超时
    while (HAL_GetTick() < timeout) {
        if (rx_buffer[0] != 0) {  // 这意味着数据已经接收到
            return SENSOR_OK;  // 数据接收成功
        }
        osDelay(1);  // 稍微延时避免CPU占用过高
    }

    last_error = SENSOR_TIMEOUT;
    return last_error;  // 超时未接收到数据
}


// UART 中断回调函数
void RS485_RxHandler(void) {
    last_error = ParseModbusResponse(rx_buffer, sizeof(rx_buffer), &sensor_data);

    if (last_error == SENSOR_OK) {
        osMessageQueuePut(sensorQueueHandle, &sensor_data, 0, 0);
    }
    // 再次开启接收
    HAL_UART_Receive_IT(sensor_huart, rx_buffer, sizeof(rx_buffer));
}


//------------报错显示屏幕------------
// void Display_Error(SensorError_t error) {
//     u8g2_ClearBuffer(&u8g2);
//     u8g2_SetFont(&u8g2, u8g2_font_6x12_tr);
//
//     // 根据错误枚举值显示对应的错误信息
//     switch (error) {
//         case SENSOR_OK:
//             u8g2_DrawStr(&u8g2, 10, 20, "Sensor OK");
//             break;
//         case SENSOR_CRC_ERROR:
//             u8g2_DrawStr(&u8g2, 10, 20, "CRC Error");
//             break;
//         case SENSOR_TIMEOUT:
//             u8g2_DrawStr(&u8g2, 10, 20, "Timeout Error");
//             break;
//         case SENSOR_INVALID_RESPONSE:
//             u8g2_DrawStr(&u8g2, 10, 20, "Invalid Response");
//             break;
//         case SENSOR_INVALID_DATA:
//             u8g2_DrawStr(&u8g2, 10, 20, "Invalid Data");
//             break;
//         default:
//             u8g2_DrawStr(&u8g2, 10, 20, "Unknown Error");
//             break;
//     }
//     u8g2_SendBuffer(&u8g2);
// }
